From: David Polakovic Date: Tue, 3 Mar 2026 05:05:00 +0000 (+0100) Subject: chore: Initial commit after server migration. X-Git-Tag: 1.0.0 X-Git-Url: https://git.dpolakovic.space/%22%22.esc_url%28%24base_url%29.%22//%22%24link/%22/%22%22.esc_url%28%24base_url%29.%22//%22%24link/%22?a=commitdiff_plain;ds=sidebyside;p=copy2fat32 chore: Initial commit after server migration. --- fa4b4a9d9e51a4c35edfed1968b38db830bf4a4e diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..10bc13c --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,127 @@ +The "Artistic License" + + Preamble + +The intent of this document is to state the conditions under which a +Package may be copied, such that the Copyright Holder maintains some +semblance of artistic control over the development of the package, +while giving the users of the package the right to use and distribute +the Package in a more-or-less customary fashion, plus the right to make +reasonable modifications. + +Definitions: + + "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes + of the Copyright Holder as specified below. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + "You" is you, if you're thinking about copying or distributing + this Package. + + "Reasonable copying fee" is whatever you can justify on the + basis of media cost, duplication charges, time of people involved, + and so on. (You will not be required to justify it to the + Copyright Holder, but only to the computing community at large + as a market that must bear the fee.) + + "Freely Available" means that no fee is charged for the item + itself, though there may be fees involved in handling the item. + It also means that recipients of the item may redistribute it + under the same conditions they received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications +derived from the Public Domain or from the Copyright Holder. A Package +modified in such a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided +that you insert a prominent notice in each changed file stating how and +when you changed that file, and provided that you do at least ONE of the +following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or + an equivalent medium, or placing the modifications on a major archive + site such as uunet.uu.net, or by allowing the Copyright Holder to include + your modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided, and provide + a separate manual page for each non-standard executable that clearly + documents how it differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or +executable form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where + to get the Standard Version. + + b) accompany the distribution with the machine-readable source of + the Package with your modifications. + + c) give non-standard executables non-standard names, and clearly + document the differences in manual pages (or equivalent), together + with instructions on where to get the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this +Package. You may not charge a fee for this Package itself. However, +you may distribute this Package in aggregate with other (possibly +commercial) programs as part of a larger (possibly commercial) software +distribution provided that you do not advertise this Package as a +product of your own. You may embed this Package's interpreter within +an executable of yours (by linking); this shall be construed as a mere +form of aggregation, provided that the complete Standard Version of the +interpreter is so embedded. + +6. The scripts and library files supplied as input to or produced as +output from the programs of this Package do not automatically fall +under the copyright of this Package, but belong to whoever generated +them, and may be sold commercially, and may be aggregated with this +Package. If such scripts or library files are aggregated with this +Package via the so-called "undump" or "unexec" methods of producing a +binary executable image, then distribution of such an image shall +neither be construed as a distribution of this Package nor shall it +fall under the restrictions of Paragraphs 3 and 4, provided that you do +not represent such an executable image as a Standard Version of this +Package. + +7. C subroutines (or comparably compiled subroutines in other +languages) supplied by you and linked into this Package in order to +emulate subroutines and variables of the language defined by this +Package shall not be considered part of this Package, but are the +equivalent of input as in Paragraph 6, provided these subroutines do +not change the language in any way that would cause it to fail the +regression tests for the language. + +8. Aggregation of this Package with a commercial distribution is always +permitted provided that the use of this Package is embedded; that is, +when no overt attempt is made to make this Package's interfaces visible +to the end user of the commercial distribution. Such use shall not be +construed as a distribution of this Package. + +9. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End \ No newline at end of file diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..af63f5d --- /dev/null +++ b/README.txt @@ -0,0 +1,30 @@ +Copy to FAT32 +Tool for copying large files to FAT32 partitions. +copyright 2025, David Polakovic, licensed under GPLv3 + +ABOUT: +This scrip copies files to FAT32 partitions. Even those +larger than 4GBs... which is needed when device using the +USB stick can read only FAT32 partitions. + +HOW TO RUN: +Navigate to the directory where you downloaded the script and +then use: + perl copy2fat32.pl +example: + perl copy2fat32.pl /home/user/large_file.aaa /run/media/user/your_usb_stick/ + +If you don't know the path to your USB stick, use command "lsblk" +to find it. + + +LICENSE: +https://www.gnu.org/licenses/gpl-3.0.en.html +see LICENSE.txt + +CONTACT: +email@dpolakovic.space +Fetch my GPG here: https://dpolakovic.space/gpg.html + +RELEASE NOTES: +1.0 - copies everything as it should diff --git a/copy2fat32.pl b/copy2fat32.pl new file mode 100644 index 0000000..d111f1f --- /dev/null +++ b/copy2fat32.pl @@ -0,0 +1,127 @@ +#!/usr/bin/perl +use strict; +use warnings; +use File::Basename; +use File::Copy; +use File::Spec; + +# split larger files to 3.5GB chunks +my $CHUNK_SIZE = 3.5 * 1024 * 1024 * 1024; # 3.5GB in bytes + +# help +sub show_usage { + print "Usage: $0 \n"; + print "To find path your USB stick try: lsblk\n" + exit; +} + +# convert bytes to human readable format +sub readable_size { + my $bytes = shift; + return sprintf("%.2f GB", $bytes / 1024 / 1024 / 1024) if $bytes > 1024*1024*1024; + return sprintf("%.2f MB", $bytes / 1024 / 1024) if $bytes > 1024*1024; + return sprintf("%.2f KB", $bytes / 1024) if $bytes > 1024; + return "$bytes bytes"; +} + +# main +sub copy_file { + my ($source, $dest_folder) = @_; + + # check input + die "File not found: $source\n" unless -f $source; + die "Destination folder not found: $dest_folder\n" unless -d $dest_folder; + + # get file info + my $file_size = -s $source; + my $filename = basename($source); + + # simple copy + if ($file_size <= $CHUNK_SIZE) { + print "Copying file...\n"; + my $destination = File::Spec->catfile($dest_folder, $filename); + copy($source, $destination) or die "Copy failed: $!\n"; + print "Copying complete!\n"; + return; + } + + ### THE MEAT: copying large files ### + print "LARGE FILE DETECTED (" . readable_size($file_size) . ")\n"; + + open my $input, '<:raw', $source or die "Cannot open $source: $!\n"; + + my $part_number = 1; + my $total_copied = 0; + my @part_files; + + # split file into chunks + while ($total_copied < $file_size) { + + # create output file for current chunk + my $part_file = File::Spec->catfile($dest_folder, "$filename.part$part_number"); + push @part_files, $part_file; + + open my $output, '>:raw', $part_file or die "Cannot create $part_file: $!\n"; + + # copy data in 1MB blocks + my $copied_this_chunk = 0; + while ($copied_this_chunk < $CHUNK_SIZE && $total_copied < $file_size) { + my $buffer; + my $bytes_read = read($input, $buffer, 1024 * 1024); + last unless $bytes_read; + + print $output $buffer; + $copied_this_chunk += $bytes_read; + $total_copied += $bytes_read; + + # progress "bar" + my $progress = int(($total_copied / $file_size) * 100); + print "\rSplitting... $progress%"; + } + + close $output; + $part_number++; + } + + close $input; + print "\nDone!\nJoining back..."; + + # rejoin the parts + print "\rJoining back... 0%"; + + my $output_file = File::Spec->catfile($dest_folder, $filename); + open my $output, '>:raw', $output_file or die "Cannot create output: $!\n"; + + my $total_parts = scalar @part_files; + my $parts_processed = 0; + + # read each part and write to final file + foreach my $part_file (@part_files) { + open my $input, '<:raw', $part_file or die "Cannot open $part_file: $!\n"; + + # copy data from part to output + my $buffer; + while (read($input, $buffer, 1024 * 1024)) { + print $output $buffer; + } + + close $input; + + # delete current part file after reading + unlink $part_file; + + # update progress + $parts_processed++; + my $progress = int(($parts_processed / $total_parts) * 100); + print "\rJoining back... $progress%"; + } + + close $output; + print "\nDone!\n"; + print "Copying complete!\n"; +} + +# showtime +show_usage() if @ARGV != 2; + +copy_file($ARGV[0], $ARGV[1]); \ No newline at end of file